Imports myBookmarks.Core
Imports myBookmarks.Infrastructure
Imports myBookmarks.Data

Namespace myBookmarks.Web
    <HandleError()> _
    <Authorize()> _
Public Class BookmarkController
        Inherits BookmarkBaseController
        Private _emailSender As IEmailSender
        Private _bookmarkRepository As IBookmarkRepository
        Private _userService As IUserService
        Public Sub New(ByVal userservice As IUserService, ByVal bookmarkRepository As IBookmarkRepository, ByVal emailsender As IEmailSender, ByVal settings As IConfigurationSettings)
            MyBase.New(userservice, bookmarkRepository, settings)
            _userService = userservice
            _emailSender = emailsender
            _bookmarkRepository = bookmarkRepository
        End Sub

        ' GET: /
        ' GET: /?label=css
        ' GET: /?label=css?page=1&sort=label 
        Public Function Index(ByVal label As String, ByVal page As System.Nullable(Of Integer), ByVal sort As String) As ActionResult
            Dim viewdata As BookmarkListViewModel = CreateBookmarkListViewModel(Of BookmarkListViewModel)(page, sort)
            viewdata.Title = "All Bookmarks"
            viewdata.SelectedMenu = "ShowAll"
            Dim blist As IEnumerable(Of BookmarkList)
            Dim total As Integer

            If label = String.Empty Then
                blist = _bookmarkRepository.GetBookmarks(CurrentUserName, viewdata.SortBy, PageCalculator.StartIndex(page, Settings.BookmarksPerPage), Settings.BookmarksPerPage, total)
            Else
                viewdata.Title = String.Format("Bookmarks labeled with {0}", label)
                blist = _bookmarkRepository.GetBookmarksByLabel(CurrentUserName, label, viewdata.SortBy, PageCalculator.StartIndex(page, Settings.BookmarksPerPage), Settings.BookmarksPerPage, total)
            End If

            viewdata.BookmarkList = blist.ToPagedList(viewdata.CurrentPage, Settings.BookmarksPerPage, total)
            Return View(viewdata)
        End Function

        ' GET: /Search?q=something
        ' GET: /Search?q=something?page=1&sort=datecreated 
        Public Function Search(ByVal q As String, ByVal page As System.Nullable(Of Integer), ByVal sort As String) As ActionResult
            Dim viewdata As BookmarkListSearchViewModel = CreateBookmarkListViewModel(Of BookmarkListSearchViewModel)(page, sort)

            viewdata.Title = String.Format("Search results for {0}", q)
            viewdata.Query = q
            Dim blist As IEnumerable(Of BookmarkList)
            Dim total As Integer
            blist = _bookmarkRepository.SearchBookmarks(CurrentUserName, q, viewdata.SortBy, PageCalculator.StartIndex(page, Settings.BookmarksPerPage), Settings.BookmarksPerPage, total)
            viewdata.BookmarkList = blist.ToPagedList(viewdata.CurrentPage, Settings.BookmarksPerPage, total)
            Return View("Index", viewdata)
        End Function

        ' GET: /AddBookmark
        Public Function AddBookmark(ByVal output As String, ByVal bkmk As String, ByVal title As String) As ActionResult
            Dim viewdata As BookmarkViewModel = CreateBookmarkViewModel(Of BookmarkViewModel)()
            viewdata.SelectedMenu = "AddBookmark"
            viewdata.Title = "Add Bookmark"
            Dim b As Bookmark
            If Not String.IsNullOrEmpty(bkmk) Then
                b = _bookmarkRepository.GetBookmarksByLocation(CurrentUserName, bkmk)
                If Not b Is Nothing Then
                    Return RedirectToAction("EditBookmark", New With {.id = b.BookmarkId, .output = output})
                End If
            End If
            b = New Bookmark With {.Location = bkmk, .Name = title}
            viewdata.Bookmark = b
            viewdata.IsPopup = If(output = "popup", True, False)
            If viewdata.IsPopup Then
                Return View("BookmarkPopUp", viewdata)
            End If
            Return View(viewdata)
        End Function

        <AcceptVerbs(HttpVerbs.Post)> _
        Public Function AddBookmark(ByVal name As String, ByVal location As String, ByVal labelnames As String, ByVal notes As String, ByVal output As String) As ActionResult
            Dim b As Bookmark
            Dim viewdata As BookmarkViewModel = CreateBookmarkViewModel(Of BookmarkViewModel)()
            viewdata.SelectedMenu = "AddBookmark"
            viewdata.Title = "Add Bookmark"
            viewdata.IsPopup = If(output = "popup", True, False)
            If String.IsNullOrEmpty(location) Then Me.ModelState.AddModelError("Location", "Please Enter a Valid Location")
            If ModelState.IsValid Then
                b = _bookmarkRepository.GetBookmarksByLocation(CurrentUserName, location)
                If b Is Nothing Then b = New Bookmark With {.UserName = CurrentUserName}
                b.Name = name
                b.Location = location
                b.Notes = notes
                b.AddLabel(labelnames)
                _bookmarkRepository.SaveBookmark(b)
                viewdata.Bookmark = b
                If viewdata.IsPopup Then
                    viewdata.ClosePopup = True
                    Return View("BookmarkPopUp", viewdata)
                Else
                    Return RedirectToAction("Index")
                End If
            End If
            viewdata.Bookmark = New Bookmark
            Return View(viewdata)
        End Function
        ' GET: /EditBookmark
        Public Function EditBookmark(ByVal id As Integer, ByVal output As String) As ActionResult
            Dim viewdata As BookmarkViewModel = CreateBookmarkViewModel(Of BookmarkViewModel)()
            viewdata.SelectedMenu = "EditBookmark"
            viewdata.Title = "Edit Bookmark"
            viewdata.IsPopup = If(output = "popup", True, False)
            Try
                Dim bookmark As Bookmark = _bookmarkRepository.GetBookmarkById(id)
                If bookmark Is Nothing Then
                    Return View("NotFound", viewdata)
                End If
                viewdata.Bookmark = bookmark
                viewdata.IsPopup = If(output = "popup", True, False)
                If viewdata.IsPopup Then
                    Return View("BookmarkPopUp", viewdata)
                End If
                Return View(viewdata)
            Catch ex As Exception
                ModelState.AddModelError("_FORM", "Error Occured")
            End Try
            Return Nothing
        End Function
        <AcceptVerbs(HttpVerbs.Post)> _
        Public Function EditBookmark(ByVal id As Integer, ByVal name As String, ByVal location As String, ByVal labelnames As String, ByVal notes As String, ByVal output As String) As ActionResult
            Dim viewdata As BookmarkViewModel = CreateBookmarkViewModel(Of BookmarkViewModel)()
            viewdata.SelectedMenu = "EditBookmark"
            viewdata.Title = "Edit Bookmark"
            viewdata.IsPopup = If(output = "popup", True, False)
            If String.IsNullOrEmpty(location) Then Me.ModelState.AddModelError("Location", "Please Enter a Valid Location")
            If ModelState.IsValid Then
                Dim b As Bookmark = _bookmarkRepository.GetBookmarkById(id)
                If Not b Is Nothing Then
                    If b.UserName <> CurrentUserName Then
                        Return View("Error")
                    End If
                Else
                    b = New Bookmark With {.UserName = CurrentUserName}
                End If
                b.Name = name
                b.Location = location
                b.Notes = notes
                b.AddLabel(labelnames)
                _bookmarkRepository.SaveBookmark(b)
                viewdata.Bookmark = b
                If viewdata.IsPopup Then
                    viewdata.ClosePopup = True
                    Return View("BookmarkPopUp", viewdata)
                Else
                    Return RedirectToAction("Index")
                End If
            End If
            viewdata.Bookmark = New Bookmark
            Return View(viewdata)
        End Function
        ' GET: /DeleteBookmark/2 
        '-Called from jquery Ajax
        <AcceptVerbs(HttpVerbs.Post)> _
        Public Function DeleteBookmark(ByVal id As Integer) As ActionResult
            Try
                Dim b As Bookmark = _bookmarkRepository.GetBookmarkById(id)
                If Not b Is Nothing Then
                    _bookmarkRepository.DeleteBookmark(b)
                    Return Content("true")
                End If
            Catch ex As Exception
                Throw ex
            End Try
            Return Content("false")
        End Function
        ' Post: /EmailBookmark
        '-Called from jquery Ajax - Passed as query string parameters
        <AcceptVerbs(HttpVerbs.Post)> _
        Public Function EmailBookmark(ByVal id As String, ByVal emailto As String, ByVal subject As String, ByVal message As String) As ActionResult
            Try
                Dim b As Bookmark = _bookmarkRepository.GetBookmarkById(id)
                Dim errormessage As String = String.Empty
                Dim u As User = CurrentUser
                If Not b Is Nothing Then
                    Dim lstOfEmails() As String = emailto.Split(New Char() {","c}, StringSplitOptions.RemoveEmptyEntries)
                    If lstOfEmails.Length > 0 AndAlso Not String.IsNullOrEmpty(emailto) Then


                        For Each email As String In lstOfEmails
                            If Helpers.IsEmail(email) Then
                                u.AddUserContact(email)
                                _emailSender.SendBookmarkEmail(emailto, CurrentUser.UserName, b, subject, message)
                            Else
                                errormessage = String.Format("{0} is not a valid email address", email)
                                Return Json(New With {.isSuccessfull = False, .message = errormessage})
                            End If
                        Next
                        _userService.SaveUser(u)
                        Return Json(New With {.isSuccessfull = True, .message = "The bookmark link was emailed successfully."})
                    Else
                        Return Json(New With {.isSuccessfull = False, .message = "Please enter a email to send."})
                    End If
                End If
            Catch ex As Exception
                Throw ex
            End Try
            Return Json(New With {.isSuccessfull = False, .message = "An unexpected error while sending email."})
        End Function
        ' Get: /GetLabelMenus
        '-Called from jquery Ajax for the side bar
        <AcceptVerbs(HttpVerbs.Get)> _
        Public Function GetLabelMenus() As PartialViewResult
            Dim viewdata As BookmarkViewModel = CreateBookmarkViewModel(Of BookmarkViewModel)()
            Return PartialView("LabelMenu", viewdata.LabelCountByBookmarks)
        End Function

        ' Get: /Manage Labels
        Public Function ManageLabels()
            Dim viewdata As BookmarkViewModel = CreateBookmarkViewModel(Of BookmarkViewModel)()
            viewdata.SelectedMenu = "ManageLabels"
            viewdata.Title = "Manage Labels"
            Return View(viewdata)
        End Function

        <AcceptVerbs(HttpVerbs.Post)> _
       Public Function ManageLabels(ByVal id As Integer, ByVal value As String) As ActionResult
            Dim l As New Label With {.UserName = CurrentUserName, .LabelId = id, .LabelName = value.Trim}
            _bookmarkRepository.SaveLabel(l)
            Return Content(l.LabelName)
        End Function
        ' Post: /DeleteLabel/2
        ' Called from jquery Ajax 
        <AcceptVerbs(HttpVerbs.Post)> _
        Public Function DeleteLabel(ByVal id As Integer) As ActionResult
            _bookmarkRepository.RemoveLabel(id)
            Return Content("false")
        End Function

        ' Get: /DeleteAll
        Public Function DeleteAll() As ActionResult
            Dim viewdata As BookmarkViewModel = CreateBookmarkViewModel(Of BookmarkViewModel)()
            viewdata.SelectedMenu = "DeleteAll"
            viewdata.Title = "Delete All"
            Return View("DeleteAll", viewdata)
        End Function

        <AcceptVerbs(HttpVerbs.Post)> _
       Public Function DeleteAll(ByVal form As FormCollection) As ActionResult
            Try
                _bookmarkRepository.DeleteAllBookmarks(CurrentUserName)
                TempData(TempDataKeys.Message) = "All bookmarks were deleted."
                Return RedirectToAction("Index")
            Catch ex As Exception
                Throw ex
            End Try
            TempData(TempDataKeys.Message) = "An unexpected error while deleting bookmarks."
            Return RedirectToAction("DeleteAll")
        End Function
        ' Get: /UserAccount
        Public Function UserAccount(ByVal selectedTab As String) As ActionResult
            Dim viewdata As BookmarkUserViewModel = CreateBookmarkUserViewModel(Of BookmarkUserViewModel)(selectedTab)
            viewdata.Title = String.Format("UserAccount : {0}", CurrentUser.ToString)
            Return View("UserAccount", viewdata)
        End Function

        <AcceptVerbs(HttpVerbs.Post)> _
       Function ChangePassword(ByVal currentPassword As String, ByVal newPassword As String, ByVal confirmPassword As String) As ActionResult
            Dim viewdata As BookmarkUserViewModel = CreateBookmarkUserViewModel(Of BookmarkUserViewModel)("changepassword")
            viewdata.Title = String.Format("UserAccount : {0}", CurrentUser.ToString)
            Dim user As User = viewdata.CurrentUser
            If Not ValidateChangePassword(currentPassword, newPassword, confirmPassword) Then
                Return View("UserAccount", viewdata)
            End If
            If Not _userService.ValidateUser(user, currentPassword) Then
                ModelState.AddModelError("currentPassword", "The current password is incorrect.")
                Return View("UserAccount", viewdata)
            End If

            If Not _userService.ChangePassword(user, newPassword) Then
                ModelState.AddModelError("currentPassword", "The current password is incorrect or the new password is invalid.")
                Return View("UserAccount", viewdata)
            End If
            TempData(TempDataKeys.Message) = "Password was changed successfully."
            Return RedirectToAction("UserAccount", New With {.selectedTab = "changepassword"})

        End Function

        <AcceptVerbs(HttpVerbs.Post)> _
        Public Function UserAccount(ByVal username As String, ByVal firstname As String, ByVal lastname As String) As ActionResult
            Dim viewdata As BookmarkUserViewModel = CreateBookmarkUserViewModel(Of BookmarkUserViewModel)("profile")
            viewdata.Title = String.Format("UserAccount : {0}", CurrentUser.ToString)
            Dim user As User = viewdata.CurrentUser
            user.FirstName = firstname
            user.LastName = lastname
            user.LastVisited = DateTime.Now
            _userService.SaveUser(user)
            TempData(TempDataKeys.Message) = "User details was saved successfully."
            Return RedirectToAction("UserAccount")
        End Function

        ' Get: /ExportBookmark 
        ' Returns custom action result
        Public Function ExportBookmark() As ExportToHtmlResult
            Dim bookmarks As List(Of BookmarkList) = _bookmarkRepository.GetBookmarks(CurrentUserName, SortBy.DateCreated, 0, Integer.MaxValue, Nothing)
            Dim allLabels As List(Of Label) = _bookmarkRepository.GetLabels(CurrentUserName)
            Dim exportModel As New ExportDataModel With {.AllLabels = allLabels, .Bookmarklist = bookmarks}
            Dim _content As String = RenderViewToString("ExportBookmark", exportModel)
            Return New ExportToHtmlResult With {.Content = _content, .Name = String.Format("{0} - Bookmarks.html", CurrentUserName)}
        End Function

        Private Function ValidateChangePassword(ByVal currentPassword As String, ByVal newPassword As String, ByVal confirmPassword As String) As Boolean
            If String.IsNullOrEmpty(currentPassword) Then
                ModelState.AddModelError("currentPassword", "Please specify the current password.")
            End If
            If String.IsNullOrEmpty(newPassword) Then
                ModelState.AddModelError("newPassword", "Please specify a new password.")
            End If

            If Not String.Equals(newPassword, confirmPassword, StringComparison.Ordinal) Then
                ModelState.AddModelError("_FORM", "The new password and confirmation password do not match.")
            End If

            Return ModelState.IsValid
        End Function
        Private Function CreateBookmarkListViewModel(Of T As {BookmarkListViewModel, New})(ByVal page As Nullable(Of Integer), ByVal sort As String) As T
            Dim viewData As T = CreateBookmarkViewModel(Of T)()
            viewData.TotalPerPage = Settings.BookmarksPerPage
            viewData.SortBy = If(sort = "", SortBy.Title, DirectCast([Enum].Parse(GetType(SortBy), sort, True), SortBy))
            viewData.CurrentPage = If(page.HasValue, page.Value - 1, 0)

            Return viewData
        End Function
        Private Function CreateBookmarkUserViewModel(Of T As {BookmarkUserViewModel, New})(ByVal selectedtab As String) As T
            Dim viewData As T = CreateBookmarkViewModel(Of T)()
            viewData.SelectedTab = If(String.IsNullOrEmpty(selectedtab), "profile", selectedtab)
            viewData.Title = CurrentUserName
            Return viewData
        End Function


    End Class
End Namespace